package cn.iocoder.yudao.module.product.aop;

import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder;
import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils;
import jakarta.servlet.http.HttpServletRequest;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import java.util.Arrays;



/**
 * 租户上下文 AOP 切面
 *
 * @author 芋道源码
 */
/*
* @Aspect：作用是把当前类标识为一个切面供容器读取

@Pointcut：定义切入点，Pointcut是植入Advice的触发条件。 每个Pointcut的定义包括2部分，一是表达式，二是方法签名。方法签名必须是 public及void型。 可以将Pointcut中的方法看作是一个被Advice引用的助记符，因为表达式不直观，因此我们可以通过方法签名的方式为 此表达式命名。 因此Pointcut中的方法只需要方法签名，而不需要在方法体内编写实际代码。

@Around：环绕增强，相当于MethodInterceptor(方法拦截器)

@AfterReturning：后置增强，相当于AfterReturningAdvice，方法正常退出时执行

@Before：标识一个前置增强方法，相当于BeforeAdvice的功能，相似功能的还有

@AfterThrowing：异常抛出增强，相当于ThrowsAdvice(异常通知)

@After: final增强，不管是抛出异常或者正常退出都会执行
*
* */
@Aspect
@Component
@Order(-1000) // 确保此切面先于其他切面执行
public class TenantContextAspect {

    private static final Logger logger = LoggerFactory.getLogger(TenantContextAspect.class);

    @Pointcut("@annotation(cn.iocoder.yudao.module.product.aop.TenantContext)")
    public void tenantContextPointCut() {
        logger.info("Entering method: {tenantContextPointCut}");
    }

    @Before("tenantContextPointCut()")
    public void before(JoinPoint joinPoint) {
        // 日志记录
        logger.info("------before----Entering method: {} with arguments: {}", joinPoint.getSignature().getName(), Arrays.toString(joinPoint.getArgs()));
        // 使用 System.out.println 记录日志
        System.out.println("before------------Entering method: " + joinPoint.getSignature().getName() +
                " with arguments: " + Arrays.toString(joinPoint.getArgs()));
    }

    @Around("tenantContextPointCut()")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
       /* HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();

        // 设置租户ID
        Long tenantId = WebFrameworkUtils.getTenantId(request);
        if (tenantId != null) {
            TenantContextHolder.setTenantId(tenantId);
        } else {
            TenantContextHolder.setTenantId(1L); // 默认设置为1L
        }*/
        System.out.println("around------tenantContextPointCut-------------111 ");
        TenantContextHolder.setTenantId(1L);
        try {
            // 继续执行目标方法
            return joinPoint.proceed();
        } finally {
            // 清除租户ID
            TenantContextHolder.clear();

            System.out.println("around------tenantContextPointCut-------------222 ");
        }
    }

    @After("tenantContextPointCut()")
    public void after(JoinPoint joinPoint) {
        // 日志记录
        logger.info("-after----Exiting method: {}", joinPoint.getSignature().getName());
        // 使用 System.out.println 记录日志
        System.out.println("after-------Exiting method: " + joinPoint.getSignature().getName());
    }
}